//package 异常练习
package errstu

import (
	"errors"
	"fmt"
	"reflect"
)

//Es 输入一个int数字 不等于0的偶数通过errors.New创建异常 奇数通过fmt.Errorf创建异常
func Es(input int) (int, error) {
	if input == 0 {
		return 0, nil
	}
	var err error
	if input%2 == 0 {
		err = errors.New("创建异常方式 errors.New ")
	} else {
		err = fmt.Errorf("创建异常方式 fmt.Errorf , input is %v ", input)
	}
	return input * 2, err
}

//error接口
type MyError string

//满足error接口
func (e MyError) Error() string {
	return string(e)
}

//指定返回原始的error接口
func CheckBig(i int) (int, error) {
	if i > 10 {
		return i, nil
	} else {
		//返回实现了error接口的异常
		return 0, MyError("小了点")
	}
}

// recover() 只是针对当前函数和以及直接调用的函数可能产生的panic， 它无法处理其调用产生的其它协程的panic
func calm() {
	//p := recover()
	println(recover())
}

//堆栈错打印
func tsPanic() {
	//defer recover() 直接这样不行
	//defer calm() //这样可以,或者匿名函数方式
	//匿名函数的方式. 不要忘记延迟defer
	defer func() {
		e := recover()
		if e != nil {
			fmt.Println(e, reflect.TypeOf(e))
		}
	}()

	fmt.Println("测试开始")
	panic("错误堆栈信息")
	//fmt.Println("这里永远不会被执行到,及时recover")
}

func Trecover() {
	//defer calm() 放在这里能正常退出,但是后面的地方不会被执行到(tsPanic中定义了恢复不会打印)
	//即正常退出他声明的地方,但是所在函数的后面无法执行到
	fmt.Println("产生一个Panic")
	tsPanic()
	fmt.Println("tsPanic中定义了恢复, 使得能够恢复过来,跳过产生panic的函数继续执行")

}
